﻿#region Using Directives

using System;
using System.Collections.Generic;
using Microsoft.SharePoint.Administration;

#endregion Using Directives

namespace SharePointStu.SharePoint.Logging
{
    [System.Runtime.InteropServices.GuidAttribute("FBAF2022-DB19-4d2b-A029-948B747A4045")]
    public class Logger : SPDiagnosticsServiceBase
    {
        #region Constants

        private const string DIAGNOSTICS_AREA_NAME = "SharePointStu.SharePoint";

        #endregion Constants

        #region Constructors

        public Logger()
            : base(DIAGNOSTICS_AREA_NAME, SPFarm.Local)
        {
        }

        public Logger(SPFarm farm)
            : base(DIAGNOSTICS_AREA_NAME, farm)
        {
        }

        #endregion Constructors

        #region Overridden Methods

        protected override IEnumerable<SPDiagnosticsArea> ProvideAreas()
        {
            List<SPDiagnosticsCategory> categories = new List<SPDiagnosticsCategory>();

            foreach (string catName in Enum.GetNames(typeof(CategoryId)))
            {
                uint catId = (uint)(int)Enum.Parse(typeof(CategoryId), catName);
                categories.Add(new SPDiagnosticsCategory(catName, TraceSeverity.Verbose, EventSeverity.Error, 0, catId));
            }

            yield return new SPDiagnosticsArea(DIAGNOSTICS_AREA_NAME, categories);
        }

        #endregion Overridden Methods

        #region Public Properties

        /// <summary>
        /// Get the <see cref="T:Microsoft.SharePoint.Administration.SPDiagnosticsCategory"/> object for
        /// the <see cref="T:SharePointStu.SharePoint.Logging.CategoryId"/> provided.
        /// </summary>
        /// <param name="id">The <see cref="T:SharePointStu.SharePoint.Logging.CategoryId"/> type to retrieve.</param>
        /// <returns>A <see cref="T:Microsoft.SharePoint.Administration.SPDiagnosticsCategory"/> object.</returns>
        public SPDiagnosticsCategory this[CategoryId id]
        {
            get
            {
                return Areas[DIAGNOSTICS_AREA_NAME].Categories[id.ToString()];
            }
        }

        /// <summary>
        /// Get the diagnostics area name used for logging.
        /// </summary>
        public string DiagnosticsAreaName
        {
            get { return DIAGNOSTICS_AREA_NAME; }
        }

        #endregion Public Properties

        #region Logging Methods

        public void LogInfo(EventId eventId, CategoryId categoryId, string infoMessage)
        {
            WriteTrace((uint)eventId, Areas[DIAGNOSTICS_AREA_NAME].Categories[categoryId.ToString()], TraceSeverity.Verbose, infoMessage, null);
        }

        public void LogWarning(EventId eventId, CategoryId categoryId, string infoMessage)
        {
            WriteTrace((uint)eventId, Areas[DIAGNOSTICS_AREA_NAME].Categories[categoryId.ToString()], TraceSeverity.Unexpected, infoMessage, null);
        }

        public void LogError(EventId eventId, CategoryId categoryId, ErrorLevel errorId, string infoMessage, Exception ex)
        {
            WriteTrace((uint)eventId, Areas[DIAGNOSTICS_AREA_NAME].Categories[categoryId.ToString()], getTraceSeverity(errorId), infoMessage, null);

            if (ex != null)
            {
                WriteTrace((uint)eventId, Areas[DIAGNOSTICS_AREA_NAME].Categories[CategoryId.Error.ToString()], getTraceSeverity(errorId), string.Concat(ex.Message, " ", ex.StackTrace), null);
            }
        }

        #endregion Logging Methods

        #region Static Logging Methods

        public static void LogInfoLocal(EventId eventId, CategoryId categoryId, string infoMessage)
        {
            var logger = new Logger();
            logger.LogInfo(eventId, categoryId, infoMessage);
        }

        public static void LogWarningLocal(EventId eventId, CategoryId categoryId, string infoMessage)
        {
            var logger = new Logger();
            logger.LogWarning(eventId, categoryId, infoMessage);
        }

        public static void LogErrorLocal(EventId eventId, CategoryId categoryId, ErrorLevel errorId, string infoMessage, Exception ex)
        {
            var logger = new Logger();
            logger.LogError(eventId, categoryId, errorId, infoMessage, ex);
        }

        #endregion Static Logging Methods

        #region Private Methods

        /// <summary>
        /// Retrieve the error level at which we want to Log.
        /// </summary>
        /// <param name="error">Level of the error.</param>
        /// <returns>A <see cref="T:Microsoft.SharePoint.Administration.TraceSeverity"/> object.</returns>
        private TraceSeverity getTraceSeverity(ErrorLevel error)
        {
            switch (error)
            {
                case ErrorLevel.High:
                    return TraceSeverity.High;
                case ErrorLevel.Medium:
                    return TraceSeverity.Medium;
                case ErrorLevel.Monitorable:
                    return TraceSeverity.Monitorable;
                case ErrorLevel.Unexpected:
                    return TraceSeverity.Unexpected;
            }

            // No matching case so return as unexpected.
            return TraceSeverity.Unexpected;
        }

        #endregion Private Methods
    }
}
